package com.yunquan.ohana.base.binding.viewadapter

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.GradientDrawable
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.webkit.WebView
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.EditText
import android.widget.ImageView
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.Spinner
import android.widget.TextView
import androidx.appcompat.widget.SwitchCompat
import androidx.core.widget.NestedScrollView
import androidx.databinding.BindingAdapter
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableList
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.viewpager.widget.ViewPager
import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.jakewharton.rxbinding4.view.clicks
import com.jakewharton.rxbinding4.view.longClicks
import com.ruffian.library.widget.RTextView
import com.yunquan.ohana.base.binding.command.BindingCommand
import com.yunquan.ohana.base.binding.viewadapter.recyclerview.LayoutManagerFactory
import com.yunquan.ohana.base.binding.viewadapter.recyclerview.LineManagerFactory
import com.yunquan.ohana.base.binding.viewadapter.recyclerview.OnScrollListener
import com.yunquan.ohana.base.binding.viewadapter.recyclerview.ScrollDataWrapper
import com.yunquan.ohana.base.binding.viewadapter.scrollview.NestScrollDataWrapper
import com.yunquan.ohana.base.binding.viewadapter.spinner.IKeyAndValue
import com.yunquan.ohana.base.binding.viewadapter.viewgroup.IBindingItemViewModel
import com.yunquan.ohana.base.binding.viewadapter.viewpager.ViewPagerDataWrapper
import com.yunquan.ohana.utils.StringUtils
import me.tatarka.bindingcollectionadapter2.ItemBinding
import java.io.File
import java.util.concurrent.TimeUnit
import androidx.core.graphics.toColorInt
import com.ruffian.library.widget.RConstraintLayout
import com.ruffian.library.widget.RFrameLayout
import com.ruffian.library.widget.RView
import com.yunquan.ohana.view.CircleTextView
import com.yunquan.ohana.view.CircularProgressBar

/**
 * CompoundButton/RCheckBox监听
 * 与双向绑定 android:checked="@={...}" 兼容：
 * - 用户交互时执行 onCheckedChangedCommand
 * - 同时通知 DataBinding 的 InverseBindingListener（checkedAttrChanged）
 */
@BindingAdapter(value = ["onCheckedChangedCommand", "android:checkedAttrChanged"], requireAll = false)
fun setCheckedChanged(checkBox: CompoundButton, bindingCommand: BindingCommand<Boolean>?, attrChanged: androidx.databinding.InverseBindingListener?) {
    checkBox.setOnCheckedChangeListener { _, isChecked ->
        // 仅在用户点击时执行自定义回调，避免程序化设置导致重复业务逻辑
        if (checkBox.isPressed) {
            bindingCommand?.execute(isChecked)
        }
        // 通知 DataBinding 的双向绑定监听，使 @={...} 生效
        attrChanged?.onChange()
    }
}

/**
 * EditText 重新获取焦点事件绑定
 */
@BindingAdapter(value = ["requestFocus"], requireAll = false)
fun requestFocusCommand(edit: EditText, focus: Boolean) {
    if (focus) {
        edit.setSelection(edit.text.length)
        edit.requestFocus()
        val imm = edit.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.showSoftInput(edit, InputMethodManager.SHOW_IMPLICIT)
    }
    edit.isFocusableInTouchMode = focus
}


/**
 * EditText 文字输入时监听
 */
@BindingAdapter(value = ["textChanged"], requireAll = false)
fun addTextChangedListener(editText: EditText, textChanged: BindingCommand<String>?) {
    editText.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(
            charSequence: CharSequence,
            i: Int,
            i1: Int,
            i2: Int,
        ) {
        }

        override fun onTextChanged(
            text: CharSequence,
            i: Int,
            i1: Int,
            i2: Int,
        ) {
            textChanged?.execute(text.toString())
        }

        override fun afterTextChanged(editable: Editable) {
        }
    })
}

/**
 * EditText 文字输入后监听
 */
@BindingAdapter(value = ["afterTextChangedCommand"], requireAll = false)
fun afterTextChangedListener(editText: EditText, textChanged: BindingCommand<String>?) {
    editText.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(
            charSequence: CharSequence,
            i: Int,
            i1: Int,
            i2: Int,
        ) {
        }

        override fun onTextChanged(
            text: CharSequence,
            i: Int,
            i1: Int,
            i2: Int,
        ) {
        }

        override fun afterTextChanged(editable: Editable) {
            textChanged?.execute(editable.toString())
        }
    })
}

/**
 * ImageView 设置图片
 */
@BindingAdapter(value = ["resId"], requireAll = false)
fun setImageRes(imageView: ImageView, resId: Int?) {
    if (resId != null) {
        imageView.setImageResource(resId)
    }
}

/**
 * ImageView 设置图片
 */
@BindingAdapter(value = ["url", "placeholderRes"], requireAll = false)
fun setImageUri(imageView: ImageView, url: String?, placeholderRes: Int) {
    if (StringUtils.isEmpty(url) && placeholderRes > 0) {
        imageView.setImageResource(placeholderRes)
    } else if (!StringUtils.isEmpty(url)) {
        var file: File? = null
        if (url!!.startsWith("file://") || !url.startsWith("http")) {
            file = File(url.replace("file://", ""))
        }
        if (placeholderRes > 0) {
            Glide.with(imageView.context)
                .load(file ?: url)
                .apply(RequestOptions().placeholder(placeholderRes))
                .into(imageView)
        } else {
            Glide.with(imageView.context)
                .load(file ?: url)
                .into(imageView)
        }
    }
}

/**
 * RadioButton 选择状态
 */
@BindingAdapter(value = ["onCheckChangedCommand"], requireAll = false)
fun onCheckChangedCommand(radioButton: RadioButton, bindingCommand: BindingCommand<Boolean>) {
    radioButton.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
        bindingCommand.execute(isChecked)
    }
}

/**
 * RadioGroup 选择监听
 */
@BindingAdapter(value = ["onCheckedChangedCommand"], requireAll = false)
fun onCheckedChangedCommand(radioGroup: RadioGroup, bindingCommand: BindingCommand<Int>) {
    radioGroup.setOnCheckedChangeListener { group, checkedId ->
        val radioButton = group.findViewById<RadioButton>(checkedId)
        if (radioButton != null && radioButton.text != null) {
            bindingCommand.execute(checkedId)
        }
    }
}

/**
 * RecyclerView 设置分割线
 */
@BindingAdapter("lineManager")
fun setLineManager(
    recyclerView: RecyclerView,
    lineManagerFactory: LineManagerFactory,
) {
    recyclerView.addItemDecoration(lineManagerFactory.create(recyclerView))
}

/**
 * RecyclerView 设置LayoutManager
 */
@BindingAdapter("layoutManager")
fun setLayoutManager(
    recyclerView: RecyclerView,
    layoutManagerFactory: LayoutManagerFactory,
) {
    recyclerView.layoutManager = layoutManagerFactory.create(recyclerView)
}

/**
 * RecyclerView  滑动状态监听
 */
@BindingAdapter(
    value = ["onScrollChangeCommand", "onScrollStateChangedCommand"],
    requireAll = false
)
fun onScrollChangeCommand(
    recyclerView: RecyclerView,
    onScrollChangeCommand: BindingCommand<ScrollDataWrapper>,
    onScrollStateChangedCommand: BindingCommand<Int>,
) {
    recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        private var state: Int = 0
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)
            onScrollChangeCommand.execute(ScrollDataWrapper(dx.toFloat(), dy.toFloat(), state))
        }

        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)
            state = newState
            onScrollStateChangedCommand.execute(newState)
        }
    })
}

/**
 * RecyclerView 上拉监听
 */
@BindingAdapter("onLoadMoreCommand")
fun onLoadMoreCommand(recyclerView: RecyclerView, onLoadMoreCommand: BindingCommand<Int>) {
    val listener = OnScrollListener(onLoadMoreCommand)
    recyclerView.addOnScrollListener(listener)
}

/**
 * RecyclerView item动画
 */
@BindingAdapter("itemAnimator")
fun setItemAnimator(recyclerView: RecyclerView, animator: RecyclerView.ItemAnimator) {
    recyclerView.itemAnimator = animator
}

/**
 * ScrollView 滑动监听
 */
@BindingAdapter("onScrollChangeCommand")
fun onScrollChangeCommand(
    nestedScrollView: NestedScrollView,
    onScrollChangeCommand: BindingCommand<NestScrollDataWrapper>,
) {
    nestedScrollView.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, scrollX, scrollY, oldScrollX, oldScrollY ->
        onScrollChangeCommand.execute(
            NestScrollDataWrapper(scrollX, scrollY, oldScrollX, oldScrollY)
        )
    })
}

/**
 * Spinner 下拉选择框
 */
@BindingAdapter(
    value = ["itemDatas", "valueReply", "resource", "dropDownResource", "onItemSelectedCommand"],
    requireAll = false
)
fun onItemSelectedCommand(
    spinner: Spinner,
    itemDatas: List<IKeyAndValue>,
    valueReply: String = "",
    resource: Int = 0,
    dropDownResource: Int = 0,
    bindingCommand: BindingCommand<IKeyAndValue>,
) {
    val lists = mutableListOf<String>()
    for (iKeyAndValue in itemDatas) {
        lists.add(iKeyAndValue.getKey())
    }
    val resId = if (resource == 0) {
        android.R.layout.simple_spinner_item
    } else {
        resource
    }
    val dropResId = if (dropDownResource == 0) {
        android.R.layout.simple_spinner_dropdown_item
    } else {
        dropDownResource
    }
    val adapter = ArrayAdapter<String>(spinner.context, resId, lists)
    adapter.setDropDownViewResource(dropResId)
    spinner.adapter = adapter
    spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
        override fun onItemSelected(
            parent: AdapterView<*>?,
            view: View?,
            position: Int,
            id: Long,
        ) {
            if (itemDatas.isNotEmpty() && itemDatas.size > position) {
                val iKAV = itemDatas[position]
                bindingCommand.execute(iKAV)
            }
        }

        override fun onNothingSelected(parent: AdapterView<*>?) {
        }

    }
    if (!TextUtils.isEmpty(valueReply) && itemDatas.isNotEmpty()) {
        for (i in itemDatas.indices) {
            val iKAV = itemDatas[i]
            if (valueReply == iKAV.getValue()) {
                spinner.setSelection(i)
                return
            }
        }
    }
}

/**
 * SwipeRefresh 下拉刷新
 */
@BindingAdapter("onRefreshCommand")
fun onRefreshCommand(swipeRefreshLayout: SwipeRefreshLayout, onRefreshCommand: BindingCommand<*>) {
    swipeRefreshLayout.setOnRefreshListener {
        onRefreshCommand.execute()
    }
}

/**
 * SwipeRefresh 刷新监听
 */
@BindingAdapter("refreshing")
fun setRefreshing(swipeRefreshLayout: SwipeRefreshLayout, refreshing: Boolean) {
    swipeRefreshLayout.isRefreshing = refreshing
}

/**
 * Switch 状态设置
 */
@BindingAdapter("switchState")
fun setSwitchState(mSwitch: SwitchCompat, isChecked: Boolean) {
    mSwitch.isChecked = isChecked
}

/**
 * Switch 状态监听
 */
@BindingAdapter("onCheckedChangeCommand")
fun onCheckedChangeCommand(mSwitch: SwitchCompat, changeListener: BindingCommand<Boolean>) {
    mSwitch.setOnCheckedChangeListener { _, isChecked ->
        changeListener.execute(isChecked)
    }
}

/**
 * View
 */
/**
 * 设置背景颜色
 */
@BindingAdapter("backgroundColor")
fun backgroundColor(view: View, color: Int) {
    view.setBackgroundColor(color)
}

@BindingAdapter("backgroundRes")
fun backgroundRes(view: View, resId: Int) {
    view.setBackgroundResource(resId)
}

@BindingAdapter("drawableColor")
fun setDrawableColor(view: View, color: Int) {
    val drawable = view.background as GradientDrawable
    drawable.setColor(color)
}

//防重复点击间隔(秒)
const val CLICK_INTERVAL = 1

/**
 * 点击事件
 */
@SuppressLint("CheckResult")
@BindingAdapter(value = ["onClickCommand", "isThrottleFirst"], requireAll = false)
fun onClickCommand(view: View, clickCommand: BindingCommand<*>, isThrottleFirst: Boolean) {
    if (isThrottleFirst) {
        view.clicks()
            .throttleFirst(CLICK_INTERVAL.toLong(), TimeUnit.SECONDS)
            .subscribe {
                clickCommand.execute()
            }
    } else {
        view.clicks()
            .subscribe {
                clickCommand.execute()
            }
    }
}

/**
 * 长按事件
 */
@SuppressLint("CheckResult")
@BindingAdapter(value = ["onLongClickCommand"], requireAll = false)
fun onLongClickCommand(view: View, clickCommand: BindingCommand<*>) {
    view.longClicks()
        .subscribe {
            clickCommand.execute()
        }
}

/**
 * 当前View
 */
@BindingAdapter(value = ["currentView"], requireAll = false)
fun replyCurrentView(currentView: View, bindingCommand: BindingCommand<View>) {
    bindingCommand.execute(currentView)
}

/**
 * 设置焦点
 */
@BindingAdapter("requestFocus")
fun requestFocusCommand(view: View, needRequestFocus: Boolean) {
    if (needRequestFocus) {
        view.isFocusableInTouchMode = true
        view.requestFocus()
    } else {
        view.clearFocus()
    }
}

/**
 * 焦点状态监听
 */
@BindingAdapter("onFocusChangeCommand")
fun onFocusChangeCommand(view: View, onFocusChangeCommand: BindingCommand<Boolean>) {
    view.setOnFocusChangeListener { _, hasFocus ->
        run {
            onFocusChangeCommand.execute(hasFocus)
        }
    }
}

/**
 * View是否可视
 */
@BindingAdapter("isVisible")
fun isVisible(view: View, visibility: Boolean) {
    view.visibility = if (visibility) {
        View.VISIBLE
    } else {
        View.GONE
    }
}

/**
 * ViewGroup item选择监听
 */
@BindingAdapter("itemView", "observableList")
fun addViews(
    viewGroup: ViewGroup,
    itemBinding: ItemBinding<*>,
    viewModelList: ObservableList<IBindingItemViewModel<ViewDataBinding>>,
) {
    if (!viewModelList.isEmpty()) {
        viewGroup.removeAllViews()
        for (viewModel in viewModelList) {
            val binding = DataBindingUtil.inflate(
                LayoutInflater.from(viewGroup.context),
                itemBinding.layoutRes(),
                viewGroup,
                true
            ) as ViewDataBinding
            binding.setVariable(itemBinding.variableId(), viewModel)
            viewModel.injecDataBinding(binding)
        }
    }
}

/**
 * ViewPager 滑动事件监听
 */
@BindingAdapter(
    value = ["onPageScrolledCommand", "onPageSelectedCommand", "onPageScrollStateChangedCommand"],
    requireAll = false
)
fun onScrollChangeCommand(
    viewPager: ViewPager2,
    onPageScrolledCommand: BindingCommand<ViewPagerDataWrapper>?,
    onPageSelectedCommand: BindingCommand<Int>?,
    onPageScrollStateChangedCommand: BindingCommand<Int>?,
) {
    viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
        private var state: Int = 0
        override fun onPageScrollStateChanged(state: Int) {
            this.state = state
            onPageScrollStateChangedCommand?.execute(state)
        }

        override fun onPageScrolled(
            position: Int,
            positionOffset: Float,
            positionOffsetPixels: Int,
        ) {
            onPageScrolledCommand?.execute(
                ViewPagerDataWrapper(
                    position,
                    positionOffset,
                    positionOffsetPixels,
                    state
                )
            )
        }

        override fun onPageSelected(position: Int) {
            onPageSelectedCommand?.execute(position)
        }

    })
}

/**
 * WebView 加载URL
 */
@BindingAdapter("render")
fun loadHtml(webView: WebView, html: String) {
    webView.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null)
}

@BindingAdapter("strikeThrough")
fun setStrikeThrough(textView: TextView, isStrike: Boolean) {
    if (isStrike) {
        textView.paintFlags = textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
    } else {
        textView.paintFlags = textView.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
    }
}

@BindingAdapter(
    value = ["circleColor", "outerCircleColor"],
    requireAll = false,
)
fun setCircleColor(view: CircleTextView, circleColor: Int?, outerCircleColor: Int?) {
    if (circleColor != null) {
        view.setCircleColor(circleColor)
    }
    if (outerCircleColor != null) {
        view.setOuterCircleColor(outerCircleColor)
    }
}

@BindingAdapter(
    value = ["bgColor", "centerColor", "progressColor", "centerTextColor"],
    requireAll = false,
)
fun setCircularProgressColor(
    view: CircularProgressBar,
    bgColor: Int?,
    progressColor: Int?,
    centerColor: Int?,
    centerTextColor: Int?,
) {
    if (bgColor != null) {
        view.setProgressBgColor(bgColor)
    }
    if (progressColor != null) {
        view.setProgressColor(progressColor)
    }
    if (centerColor != null) {
        view.setCenterColor(centerColor)
    }
    if (centerTextColor != null) {
        view.setCenterTextColor(centerTextColor)
    }
}

@BindingAdapter("backgroundNormal")
fun bindBackgroundNormal(view: View, color: Int) {
    if (view is RTextView) {
        view.helper.backgroundColorNormal = color
    } else if (view is RFrameLayout) {
        view.helper.backgroundColorNormal = color
    } else if (view is RView) {
        view.helper.backgroundColorNormal = color
    } else if (view is RConstraintLayout) {
        view.helper.backgroundColorNormal = color
    }
    view.setBackgroundColor(color)
}

@BindingAdapter("textColorNormal")
fun bindTextColorNormal(view: RTextView, color: Any?) {
    when (color) {
        is Int -> {
            // 如果 ObservableField<Int> 里传的就是颜色 int
            view.helper.textColorNormal = color
        }

        is androidx.databinding.ObservableField<*> -> {
            val value = color.get()
            if (value is Int) {
                view.helper.textColorNormal = value
            }
        }

        is String -> {
            try {
                view.helper.textColorNormal = color.toColorInt()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        else -> {
            // 默认颜色
            view.helper.textColorNormal = Color.GRAY
        }
    }
}